﻿using System;
using System.Collections.ObjectModel;
using System.Composition;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using Unread.App.Common;
using Unread.App.Services.Interfaces;
using Unread.App.Views;
using Unread.Business.Repositories.Interfaces;

namespace Unread.App.ViewModels
{
    [Export]
    public class FeedItemViewModel : BindableBase
    {
        private readonly IFeedRepository _feedRepository;
        private readonly IFeedItemRepository _feedItemRepository;
        private readonly IAppLauncher _appLauncher;
        private readonly INavigationService _navigationService;

        private string _title;
        public string Title 
        { 
            get { return _title; } 
            set { SetProperty(ref _title, value); } 
        }

        private ItemViewModel _selectedItem;
        public ItemViewModel SelectedItem 
        { 
            get { return _selectedItem; } 
            set { SetProperty(ref _selectedItem, value); } 
        }

        private Guid _feedId;
        public Guid FeedId 
        {
            get { return _feedId; }
            set { SetProperty(ref _feedId, value); }
        }

        private bool _isLoading;
        public bool IsLoading
        {
            get { return _isLoading; }
            set { SetProperty(ref _isLoading, value); }
        }

        public ObservableCollection<ItemViewModel> Items { get; set; }

        [ImportingConstructor]
        public FeedItemViewModel(IFeedRepository feedRepository, IFeedItemRepository feedItemRepository, IAppLauncher appLauncher,
            INavigationService navigationService)
        {
            if (feedRepository == null) throw new ArgumentNullException("feedRepository");
            if (feedItemRepository == null) throw new ArgumentNullException("feedItemRepository");
            if (appLauncher == null) throw new ArgumentNullException("appLauncher");
            if (navigationService == null) throw new ArgumentNullException("navigationService");

            _feedRepository = feedRepository;
            _feedItemRepository = feedItemRepository;
            _appLauncher = appLauncher;
            _navigationService = navigationService;

            Items = new ObservableCollection<ItemViewModel>();
            OpenFeedItemLinkCommand = new DelegateCommand(OpenFeedItemLink, CanOpenFeedItemLink);
            HomeCommand = new DelegateCommand(GoHome);
        }

        public async Task Load(Guid feedId, Uri feedItemUri)
        {
            var feed = await _feedRepository.GetById(feedId);
            if (feed == null)
                throw new InvalidOperationException(string.Format("Feed not found by id '{0}'", feedId));

            FeedId = feedId;
            Title = feed.Title;

            var items = await _feedItemRepository.GetAll(feed.SyndicationUri);
            foreach (var item in items)
            {
                Items.Add(new ItemViewModel
                {
                    FeedItemId = item.Id,
                    Title = item.Title,
                    Content = item.Summary,
                    Link = item.Link
                });
            }

            SelectedItem = Items.FirstOrDefault(i => 
                Uri.Compare(i.Link, feedItemUri, UriComponents.AbsoluteUri, UriFormat.Unescaped, StringComparison.CurrentCultureIgnoreCase) == 0);

            if (SelectedItem == null)
                SelectedItem = Items.FirstOrDefault();
        }

        #region OpenFeedItemCommand

        public ICommand OpenFeedItemLinkCommand { get; set; }

        private bool CanOpenFeedItemLink(object arg)
        {
            return (SelectedItem as ItemViewModel != null);
        }

        private async void OpenFeedItemLink(object obj)
        {
            var feedItem = ((ItemViewModel)SelectedItem);
            await _appLauncher.LaunchUriAsync(feedItem.Link);
        }

        #endregion

        #region HomeCommand

        public ICommand HomeCommand { get; set; }

        private void GoHome(object obj)
        {
            _navigationService.Navigate(typeof(UnreadPage));
        }

        #endregion
    }
}
